﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace PeekWebApp.handler
{
    /// <summary>
    /// ValidateCodeHandler 的摘要说明
    /// </summary>
    public class ValidateCodeHandler : IHttpHandler
    {
        private static string[] _FontFamilies = { "Arial", "Comic Sans MS", "Courier New", "Georgia", "Lucida Console", "MS Sans Serif", "Stencil", "Tahoma", "Times New Roman", "Trebuchet MS", "Verdana" };
        private static Random _Rand = new Random();
        private static FontFamily GetFont()
        {

            FontFamily _font = null;
            while (_font == null)
            {
                try
                {
                    _font = new FontFamily(_FontFamilies[_Rand.Next(_FontFamilies.Length)]);
                }
                catch (Exception ex)
                {
                    _font = null;
                }
            }

            return _font;
        }
        private static PointF RandomPoint(int xmin, int xmax, int ymin, int ymax)
        {
            return new PointF(_Rand.Next(xmin, xmax), _Rand.Next(ymin, ymax));
        }
        private static void WarpText(GraphicsPath textPath, Rectangle rect)
        {

            int intWarpDivisor = 0;
            RectangleF rectF = new RectangleF(0, 0, rect.Width, rect.Height);

            intWarpDivisor = _Rand.Next(4, 8);

            int intHrange = Convert.ToInt32(rect.Height / intWarpDivisor);
            int intWrange = Convert.ToInt32(rect.Width / intWarpDivisor);

            PointF p1 = RandomPoint(0, intWrange, 0, intHrange);

            PointF p2 = RandomPoint(rect.Width - (intWrange - Convert.ToInt32(p1.X)), rect.Width, 0, intHrange);
            PointF p3 = RandomPoint(0, intWrange, rect.Height - (intHrange - Convert.ToInt32(p1.Y)), rect.Height);
            PointF p4 = RandomPoint(rect.Width - (intWrange - Convert.ToInt32(p3.X)), rect.Width, rect.Height - (intHrange - Convert.ToInt32(p2.Y)), rect.Height);

            PointF[] points = new PointF[] { p1, p2, p3, p4 };
            Matrix m = new Matrix();
            m.Translate(0, 0);

            textPath.Warp(points, rectF, m, WarpMode.Perspective, 0);
        }
        private static GraphicsPath CreateText(string text, int width, int height, Graphics g)
        {

            GraphicsPath textPath = new GraphicsPath();
            FontFamily ff = GetFont();
            int emSize = (int)width * 2 / text.Length;
            Font f = null;
            try
            {
                SizeF measured = new SizeF(0, 0);
                SizeF workingSize = new SizeF(width, height);
                while ((emSize > 2))
                {
                    f = new Font(ff, emSize);
                    measured = g.MeasureString(text, f);
                    if (!(measured.Width > workingSize.Width | measured.Height > workingSize.Height))
                    {
                        break; // TODO: might not be correct. Was : Exit While
                    }
                    f.Dispose();
                    emSize -= 2;
                }
                emSize += 8;
                f = new Font(ff, emSize);

                StringFormat fmt = new StringFormat();
                fmt.Alignment = StringAlignment.Center;
                fmt.LineAlignment = StringAlignment.Center;

                textPath.AddString(text, f.FontFamily, (int)f.Style, f.Size, new RectangleF(0, 0, width, height), fmt);

                WarpText(textPath, new Rectangle(0, 0, width, height));
            }
            catch (Exception ex)
            {
            }
            finally
            {
                f.Dispose();
            }


            return textPath;
        }
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "image/jpg";
            int width = 100;
            int height = 28;
            string w = context.Request.QueryString["w"];
            string h = context.Request.QueryString["h"];
            string c = context.Request.QueryString["c"];
            string f = context.Request.QueryString["f"];
            string b = context.Request.QueryString["b"];
            if (int.TryParse(w, out width) == false)
            {
                width = 100;
            }
            if (int.TryParse(h, out height) == false)
            {
                height = 28;
            }
            if (string.IsNullOrEmpty(c)) return;
            string backgroundimage = "";
            string code = c.Length > 5 ? c.Substring(0, 5) : c;


            Color frontColor = Color.Black;
            Color bgColor = Color.BlanchedAlmond;
            try
            {

            }
            catch { }
            Bitmap bmp = null;
            Graphics g = null;
            if (string.IsNullOrEmpty(backgroundimage))
            {
                bmp = new Bitmap(width, height);
                g = Graphics.FromImage(bmp);
                g.FillRectangle(new SolidBrush(bgColor), 0, 0, width, height);
            }
            else
            {
                bmp = Bitmap.FromFile(context.Server.MapPath(backgroundimage)) as Bitmap;
            }
            g = Graphics.FromImage(bmp);

            GraphicsPath textPath = CreateText(code, width, height, g);
            g.FillPath(new SolidBrush(frontColor), textPath);
            bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}